package com.mingqijia.gassafety.shared.utils;

import com.gap.basic.exception.BizException;
import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.util.zip.CRC32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;


public class ZipUtil {


    /**
     * @param srcPath     要压缩的源文件路径。如果要压缩一个文件，则为文件的全路径；如果 要压缩一个目录，则为该目录的顶层目录路径
     * @param zipPath     压缩文件保存的路径。 zipPath不能是srcPath路径下的子文件夹
     * @param zipFileName 压缩文件名
     */

    public static void preZip(final String srcPath, final String zipPath, final String zipFileName) throws IOException {

        if (StringUtils.isEmpty(srcPath) || StringUtils.isEmpty(zipPath) || StringUtils.isEmpty(zipFileName)) {
            throw new BizException("文件路径为空");
        }
        CheckedOutputStream cos = null;
        ZipOutputStream zos = null;
        try {
            File srcFile = new File(srcPath);
            // 判断压缩文件的路径是否为源文件路径的子文件夹，防止无限递归的出现
            if (srcFile.isDirectory() && zipPath.indexOf(srcPath) != -1) {
                throw new BizException("压缩文件的路径不能再源文件的路径中");
            }
            File zipDir = new File(zipPath);
            // 判断压缩文件的路径是否存在，不存在创建
            if (!zipDir.exists() || !zipDir.isDirectory()) {
                zipDir.mkdirs();
            }
            StringBuffer sb = new StringBuffer();
            String zipFilePath = sb.append(zipPath).append(File.separator).append(zipFileName).toString();
            File zipFile = new File(zipFilePath);
            if (zipFile.exists()) {
                // 检查文件是否允许删除，不允许则抛出SecurityException
                SecurityManager securityManager = new SecurityManager();
                securityManager.checkDelete(zipFilePath);
                zipFile.delete();
            }
            cos = new CheckedOutputStream(new FileOutputStream(zipFile), new CRC32());
            zos = new ZipOutputStream(cos);
            // 如果只是压缩一个文件则需要截取该文件的父目录
            String srcRootDir = srcPath;
            if (srcFile.isFile()) {
                int index = srcPath.lastIndexOf(File.separator);
                if (index != -1) {
                    srcRootDir = srcPath.substring(0, index);
                }
            }
            // 调用压缩方法
            zip(srcRootDir, srcFile, zos);
            zos.flush();
        } finally {
            if (zos != null) {
                zos.close();
            }
        }
    }

    /**
     * 递归压缩文件夹
     *
     * @param srcRootDir
     * @param file
     * @param zos
     */
    public static void zip(final String srcRootDir, final File file, final ZipOutputStream zos) throws IOException {

        if (file == null) {
            return;
        }
        // 如果是文件直接压缩
        if (file.isFile()) {
            int count;
            int bufferLen = 1024;
            byte[] byteData = new byte[bufferLen];
            // 获取文件相对于压缩文件夹根目录的子路径，作为zipEntry的name
            String subPath = file.getAbsolutePath();
            int index = subPath.indexOf(srcRootDir);
            if (index != -1) {
                subPath = subPath.substring(srcRootDir.length());
            }
            ZipEntry entry = new ZipEntry(subPath);
            zos.putNextEntry(entry);
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
            try {
                while ((count = bis.read(byteData, 0, bufferLen)) != -1) {
                    zos.write(byteData, 0, count);
                }
            } finally {
                if (bis != null) {
                    bis.close();
                }
                if (zos != null) {
                    zos.closeEntry();
                }
            }
        } else {
            // 递归压缩文件夹的内容
            File[] childrenFiles = file.listFiles();
            if (childrenFiles != null) {
                for (File child : childrenFiles) {
                    zip(srcRootDir, child, zos);
                }
            }
        }
    }
}
